/*-----------------------------------------------------------------------------
 *
 *        FILE: sgidLnxUtils.c
 * DESCRIPTION: contains routines to get the Hard Disk serial number or the
 *              MAC address
 *
 *-----------------------------------------------------------------------------
 */


#include <linux/hdreg.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/socket.h>

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

/*-----------------------------------------------------------------------------
 *
 * DESCRIPTION: get the Hard disk serial number
 *       INPUT: char *devname - device name to check
 *              int debugFlag - whether or not to print debug information
 *              char *buffer  - location to return the serial number
 *      OUTPUT: debug information if debugFlag is true
 *      RETURN: 0 - unable to get info from device
 *              1 - success, information returned in buffer
 * ASSUMPTIONS: none.
 *
 *-----------------------------------------------------------------------------
 */
int getHDinfo ( char *devname, int debugFlag, char *buffer )
{
    struct hd_driveid id;                /* struct to store HD info */
    int fd;                              /* file descriptor for open device */
    int rc = 1;                          /* result code, assume success at first */

    /* attempt to open the requested device */
    fd = open (devname, O_RDONLY|O_NONBLOCK);

    /* if error, ten report it and return */
    if (fd < 0)
    {
        if (debugFlag) perror(devname);
        /* zero means unable to get info for this device */
        rc = 0;
    }
    /* otherwise, use ioctl() to get the device info */
    else
    {
        /* if no error, then copy out the serial number */
        if (!ioctl(fd, HDIO_GET_IDENTITY, &id))
        {
            /* if (debugFlag) printf("SerialNo=%.20s\n", id.serial_no); */

            /* copy strlen amount of data to the output buffer */
            bcopy ( id.serial_no, buffer, strlen ( (const char*)id.serial_no) );

	    /* null terminate since this is a string and bcopy () doesn't */
            buffer[strlen ( (const char*)id.serial_no) ] = '\0';
        } 
        /* otherwise, report back an error and print it if debug on */
        else
        {
            /* zero means unable to get info for this device */
            rc = 0;
            if (debugFlag)
            {
                if (errno == -ENOMSG)
                    printf(" no identification info available\n");
                else
                    perror(" HDIO_GET_IDENTITY failed");
            } /* end of if debugFlag */
        } /* end of else error in ioctl () */

        /* don't forget to close our device since we are finished */
        close (fd);
    } /* end of else no error from open () */

    /* rc should report back 1 if successful, 0 if not */
    return rc;

} /* end of getHDinfo () */


/*-----------------------------------------------------------------------------
 *
 * DESCRIPTION: get the MAC address
 *       INPUT: char *devname - device name to check
 *              int debugFlag - whether or not to print debug information
 *              char *buffer  - location to return the serial number
 *      OUTPUT: debug information if debugFlag is true
 *      RETURN: 0 - unable to get info from device
 *              1 - success, information returned in buffer
 * ASSUMPTIONS: none.
 *
 *-----------------------------------------------------------------------------
 */
int getMACaddr ( char *devname, int debugFlag, char *buffer )
{
    struct ifreq ifr;                    /* struct to store socket info */
    int sd;                              /* socket descriptor for open socket */
    int rc = 1;                          /* result code, assume success at first */

    /* try an open a socket */
    sd = socket ( AF_INET, SOCK_DGRAM, 0 );

    /* if error, then report back and print if debug on */
    if ( -1 == sd ) {
        if (debugFlag) perror(devname);
        /* zero means unable to get info for this device */
        rc = 0;
    }
    /* otherwise, use ioctl() to get the device info */
    else
    {
        /* use the device name requested */
        strcpy ( ifr.ifr_name, devname );
  
        /* if no error, then format and copy the MAC address to our 
	 * output buffer */
        if ( !ioctl(sd, SIOCGIFHWADDR, &ifr) )
        {
            /* only really interested in first 6 bytes */
            bcopy ( ifr.ifr_hwaddr.sa_data, buffer, 12 );

            /* format the output buffer */
            sprintf ( buffer, "%02x%02x%02x%02x%02x%02x",
                    ( buffer[0] & 0377 ), ( buffer[1] & 0377 ),
                    ( buffer[2] & 0377 ), ( buffer[3] & 0377 ),
                    ( buffer[4] & 0377 ), ( buffer[5] & 0377 )
                   );
        }
        /* otherwise, report back an error */
        else
        {
            /* zero means unable to get info for this device */
            rc = 0;
            if (debugFlag)
            {
                if (errno == -ENOMSG)
                    printf(" no identification info available\n");
                else
                    perror(" SIOCGIFHWADDR failed");
            } /* end of if debugFlag */
        }
  
        /* don't forget to close our device since finished */
        close(sd);
    } /* end of else */

    /* rc should report back 1 if successful, 0 if not */
    return rc;

} /* end of getMACaddr () */
